package com.tyut.musicdreamer.framework.starter.web.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import java.nio.charset.StandardCharsets;

/**
 * 内部请求认证拦截器
 * 负责验证网关传递的用户信息，并将用户ID设置到请求属性中
 */
@Component
@Slf4j
public class InternalRequestAuthInterceptor implements HandlerInterceptor {

    private static final String USER_ID_HEADER = "X-Internal-User-Id";
    private static final String USER_ROLE_HEADER = "X-Internal-User-Role";
    private static final String SIGNATURE_HEADER = "X-Internal-Signature";
    
    public static final String USER_ID_ATTRIBUTE = "userId";
    public static final String USER_ROLE_ATTRIBUTE = "userRole";

    @Value("${musicdreamer.security.signature-key:musicDreamerInternalKey}")
    private String signatureKey;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        try {
            // 从请求头中获取用户ID和角色
            String userId = request.getHeader(USER_ID_HEADER);
            String userRole = request.getHeader(USER_ROLE_HEADER);
            String signature = request.getHeader(SIGNATURE_HEADER);
            
            log.debug("处理请求: {} {}, 请求头: userId={}, userRole={}, signature={}", 
                    method, requestURI, userId, userRole, signature != null ? "存在" : "不存在");
            
            // 如果没有用户ID或签名，直接放行（可能是公开接口或直接访问）
            if (!StringUtils.hasText(userId) || !StringUtils.hasText(signature)) {
                log.debug("请求 {} {} 无用户ID或签名，可能是公开接口或直接访问", method, requestURI);
                return true;
            }
            
            // 验证签名
            String expectedSignature = generateSignature(userId, userRole);
            if (!expectedSignature.equals(signature)) {
                log.warn("请求 {} {} 签名验证失败，可能是伪造请求。预期签名: {}, 实际签名: {}", 
                        method, requestURI, expectedSignature, signature);
                // 签名验证失败，但仍然放行，只是不设置用户ID
                // 这样需要用户身份的接口会因为获取不到用户ID而拒绝请求
                return true;
            }
            
            // 签名验证成功，将用户ID和角色设置到请求属性中
            request.setAttribute(USER_ID_ATTRIBUTE, Long.parseLong(userId));
            request.setAttribute(USER_ROLE_ATTRIBUTE, userRole);
            
            log.debug("请求 {} {} 验证成功，用户ID: {}, 角色: {}", method, requestURI, userId, userRole);
        } catch (Exception e) {
            log.error("处理内部请求认证时发生错误, 请求: {} {}", method, requestURI, e);
            // 发生异常，放行但不设置用户ID
        }
        
        return true;
    }
    
    /**
     * 生成安全签名
     * 使用用户ID + 用户角色 + 签名密钥生成MD5，确保请求头不被伪造
     */
    private String generateSignature(String userId, String userRole) {
        String content = userId + ":" + userRole + ":" + signatureKey;
        return DigestUtils.md5DigestAsHex(content.getBytes(StandardCharsets.UTF_8));
    }
} 